﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MathLib;
using System.Data.OleDb;
using System.IO;

namespace Demog {


    public partial class MainForm : Form {

        private const string australianDir = "Mouse";
        private static string australianDataA =  "A.xls";
        private static string australianDataX = "X.xls";
        
        private DataGridView[] dgvs;
       
        private Matrix A;
        private Matrix x = null;
        private Matrix y = null;
        private Matrix yy = null;
        private Matrix z = null;
        private int count;
        private Matrix[] Pop;

        public MainForm() {
            InitializeComponent();
  
            dgvs = new DataGridView[] { dgvA, dgvMatrRight, dgvXX, dgvX };
            foreach (DataGridView dgv in dgvs) {
                dgv.ColumnHeadersVisible = false;
                dgv.RowHeadersVisible = false;
                dgv.AllowUserToResizeColumns = false;
                dgv.AllowUserToResizeRows = false;
                dgv.ReadOnly = true;
            }
        }

        private Matrix ReadMatrixFromGrid(DataGridView dgv) {
            DataTable dt = (DataTable)dgv.DataSource;

            return ReadMatrixFromTable(dt);
        }


        private void PrintMatrix(DataGridView dgv, Matrix m) {
            DataTable table = CreateTable(m.NoRows, m.NoCols);
            for (int i = 0; i < m.NoRows; i++) {
                DataRow dr = table.Rows[i];
                for (int j = 0; j < m.NoCols; j++)
                    dr[j] = Math.Round(m[i, j],3);
            }

            dgv.DataSource = table;
        }


        private void PrintMatrixRound(DataGridView dgv, Matrix m) {
            DataTable table = CreateTable(m.NoRows, m.NoCols);
            for (int i = 0; i < m.NoRows; i++) {
                DataRow dr = table.Rows[i];
                for (int j = 0; j < m.NoCols; j++)
                    dr[j] = Math.Round(m[i, j]);
            }

            dgv.DataSource = table;
        }


        private DataTable CreateTable(int rows, int columns) {
            DataTable t = new DataTable();
            for (int j = 0; j < columns; j++)
                t.Columns.Add();
            for (int i = 0; i < rows; i++)
                t.Rows.Add();

            return t;
        }

        private void LoadX(string fileName) {
            DataTable dtX = LoadToDataTable(fileName);
            if (dtX == null)
                return;

            dgvX.DataSource = dtX;
            x = ReadMatrixFromTable(dtX);
        }

        private void LoadA(string fileName) {
       //     A = new Matrix[australianDataA.Length];
             DataTable dtA = LoadToDataTable(fileName);
            if (dtA == null)
                return;

            dgvA.DataSource = dtA;
            A = ReadMatrixFromTable(dtA);
          
            }
        

        private DataTable LoadToDataTable(string fileName) {
            ExcelReader rdr = new ExcelReader(fileName);
            DataSet ds = rdr.ReadData();
            return ds.Tables.Count > 0 ? ds.Tables[0] : null;
        }

        private Matrix ReadMatrixFromTable(DataTable dt) {
            Matrix m = new Matrix(dt.Rows.Count, dt.Columns.Count);

            for (int i = 0; i < m.NoRows; i++) {
                DataRow dr = dt.Rows[i];
                for (int j = 0; j < m.NoCols; j++) {
                    object val = dr[j];
                    try {
                        m[i, j] = DBNull.Value.Equals(val) ? 0.0 : (double)val;
                    } catch (Exception e) {
                        throw new Exception("Ошибка формата входных данных");
                    }
                }
            }

            return m;
        }

        private void Solve_Click(object sender, EventArgs e) {
            
            if ((object)A == null || (object)x == null ) {
                MessageBox.Show("Исходные данные не заданы");
                return;
            }
            try {
                count = int.Parse(tbCount.Text);
            } catch (Exception ex) {
                throw new Exception("Ошибка формата входных данных");
            }
            Pop = new Matrix[x.NoCols];
            for (int j = 0; j < x.NoCols; j++) {
                Pop[j] = new Matrix(x.NoRows, 1);
                for (int i = 0; i < x.NoRows; i++)
                    Pop[j][i, 0] = x[i, j];
            }
            
        DemogFilterAlg df = new DemogFilterAlg(count, x.NoRows, 

            y = df.SolveReal();
            PrintMatrixRound(dgvMatrRight, y);
            yy = null;
            yy = df.SolveWithFilterReal();
            PrintMatrixRound(dgvXX, yy);
            z = Pop[count];
            PrintMatrix(dataGridView1, df.P);
            PrintMatrix(dataGridView2, df.G);
            
        }

        private void Curve_Click(object sender, EventArgs e) {
            if ((object)y == null || (object)yy == null||(object)z == null)
                return;
            Graph graph = new Graph(y, yy, z);
            graph.ShowDialog();
        }



        private void bFind_Click(object sender, EventArgs e) {

            DemogFilterAlg df = new DemogFilterAlg(count, x.NoRows, Pop, 1, 1, 1,  A);
            int expCount = int.Parse(tbExpCount.Text);
            Matrix[] xp = new Matrix[expCount];
            Matrix[] xx = new Matrix[expCount];
            for (int i = 0; i < expCount; i++) {
                xp[i] = df.SolveReal();
                xx[i] = df.SolveWithFilterReal();
            }
            Matrix sigma1 = DemogFilterAlg.CalclDeviation(Pop[count], xp);
            Matrix sigma2 = DemogFilterAlg.CalclDeviation(Pop[count], xx);
            PrintMatrix(dgvSigmaX, sigma1);
            PrintMatrix(dgvSigmaXX, sigma2);

            double s1 = 0;
            double s2 = 0;

            for (int i = 0; i < count; i++) {
                s1 += sigma1[i, 0];
                s2 += sigma2[i, 0];
            }
            double ef = Math.Round(s1 / s2, 2);
            tbEff.Text = ef.ToString();
        }

 

        private void loadA_Click(object sender, EventArgs e) {
             string fileNameA = Program.dataPath + "\\" + australianDir + "\\" + australianDataA;
            LoadA(fileNameA);

            string fileNameX = Program.dataPath + "\\" + australianDir + "\\" + australianDataX;
            LoadX(fileNameX);
            PrintMatrix(dgvA, A);
        }

    }
}